﻿using DeHeng_Mes.Constant;
using DeHeng_Mes.Dao.PlcDao;
using DeHeng_Mes.Mapper;
using DeHeng_Mes.Model;
using DeHeng_Mes.Model.Boss;
using DeHeng_Mes.Model.ConfigModel;
using DeHeng_Mes.Utils;
using S7.Net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace DeHeng_Mes.Thread
{

    public class CodeDataCollect
    {
        #region 成员实例
        PlcDao plcDao = new PlcDao();
        CodeTraceDao codeTraceDao = new CodeTraceDao();
        DataCollector collector = new DataCollector();
        Dictionary<string, Dictionary<string, bool>> saveStatus = StationSaveStatusDic.SaveStatus;
        #endregion

        /// <summary>
        /// 采集批次件
        /// </summary>
        /// <param name="types"></param>
        /// <param name="orderModel"></param>
        /// <param name="operations"></param>
        public async void BatchStationCollrction(Dictionary<object, Type> types, PlcOrderConfigModel orderModel, List<string> operations)
        {

            if (orderModel.PlcName.Equals("endWorkSpr"))
            {

            }
            foreach (var operation in operations)
            {
                try
                {
                    // 初始化工序列表
                    List<string> operationList = null;

                    // 初始化批次码存储列表
                    List<string> batchCodeList = new List<string>();

                    // 转换为程序可接受的工序号
                    (string operationReal,bool isPut) = MappingTable.GetOperation(operation, orderModel.PlcName);

                    // 判断是否是一工序对应多个实际工序
                    if (operationReal.Contains(","))
                    {
                        // 分解实际工序
                        operationList = operationReal.Split(',').ToList();
                    }
                    else
                    {
                        operationList = new List<string>()
                        {
                            operationReal
                        };
                    }


                    if (operationList != null && operationList.Count > 0)
                    {
                        foreach (string operationItem in operationList)
                        {
                            // 获取工序状态
                            bool isOk = plcDao.GetBoolFieldValue(types, SystemConstant.StationStatus, operationItem);

                            // 判断工序完成状态
                            if (isOk)
                            {
                                // 获取批次码
                                Dictionary<string, object> codeDic = plcDao.GetFieldValues(types, SystemConstant.Code);

                                // 遍历Dic并且匹配数据存入缓存列表
                                foreach (KeyValuePair<string, object> code in codeDic)
                                {
                                    // 判断Key是否包含工序
                                    if (code.Key.Contains(operationItem))
                                    {
                                        // 判断Value是否为空，为空跳过本次循环
                                        if (string.IsNullOrEmpty(code.Value.ToString()))
                                            continue;
                                        // 加入二维码列表
                                        batchCodeList.Add(code.Value.ToString());
                                    }
                                }

                                // 获取节拍
                                string beat = plcDao.GetStringFieldValue(types, SystemConstant.Beat, operationItem);

                                // 获取完成状态
                                bool operationStatus = plcDao.GetBoolFieldValue(types, SystemConstant.ProduceStatus, operationItem);

                                // 获取完成时间
                                string createTime = DateTime.Now.ToString();

                                // 工序推送,存储数据
                                BossMessager bossMessager = await OperationPutFactoryMae(types, orderModel, operation, operationList, operationStatus);

                                if (bossMessager != null && bossMessager.code == 200)
                                {
                                    foreach (var batchCode in batchCodeList)
                                    {
                                        // 批次码存库操作
                                        bool codeIsBanding = codeTraceDao.InsertBatchCode(orderModel.orderPlan.OrderId, batchCode, createTime);

                                        // 节拍存库操作
                                        bool beatIsBanding = codeTraceDao.BatchBandingBeat(batchCode, operation, beat, operationStatus, createTime);
                                        if (orderModel.PlcName.Contains("Glue"))
                                        {
                                            _ = Task.Run(() => collector.CollectDataForGluing(DateTime.Now, orderModel.orderPlan.OrderId, batchCode, operation));
                                        }


                                        if (orderModel.PlcName.Contains("Glue"))
                                        {
                                           // _ = Task.Run(() => collector.CollectDataForGluing(DateTime.Now, orderModel.orderPlan.OrderId, batchCode, operation));
                                        }

                                        if (codeIsBanding && beatIsBanding)
                                        {
                                            // Ng条码存储
                                            if (!operationStatus)
                                            {
                                                // 插入Ng工序的条码等数据，暂存数据库提供给工厂Mes接口
                                                codeTraceDao.InsertPadTrace(orderModel.orderPlan.OrderId, batchCode, operation, createTime);

                                                Tools.ProduceLogText($"{orderModel.PlcName}暂存了一条Ng数据，条码为[{batchCode}]，时间为[{createTime}]");
                                            }
                                        }
                                    }

                                    // 判断是否是下线工序
                                    if (MappingTable.GetLineIsEnd(orderModel.PlcName, operationItem))
                                        LineProcessPut(types, orderModel, operationList); // 下线推送

                                    // 获取该工序读取对应的偏移量
                                    (int startByteAdrByRead, int bitAdrByRead) = MappingTable.OperationGetReadOff(orderModel.PlcName, operationItem);

                                    // 获取该工序写入对应的偏移量
                                    (int startByteAdr, int bitAdr) = MappingTable.OperationGetOff(orderModel.PlcName, operationItem);


                                    // 重置读取信号
                                    orderModel.plc.WriteBit(DataType.DataBlock, 6000, startByteAdrByRead, bitAdrByRead, false);

                                    // 返回已读信号
                                    orderModel.plc.WriteBit(DataType.DataBlock, SystemConstant.Write, startByteAdr, bitAdr, true);
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Tools.ProduceLogTextError($"{orderModel.PlcName}数采模块内部报错，当前工序为{operation}，原因是{e.Message}");
                }
            }
        }

        /// <summary>
        /// 单站工序报工通用方法
        /// </summary>
        /// <param name="types"></param>
        /// <param name="orderModel"></param>
        /// <param name="operation"></param>
        /// <param name="operationReal"></param>
        /// <param name="operationStatus"></param>
        private async Task<BossMessager> OperationPutFactoryMae(Dictionary<object, Type> types, PlcOrderConfigModel orderModel, string operation, List<string> operationList, bool operationStatus)
        {
            // 初始化产量字段
            decimal realCount = 0;
            decimal realCountNg = 0;

            // 遍历获取产量
            foreach (var operationItem in operationList)
            {
                // 获取产量字段
                string v = plcDao.GetStringFieldValue(types, SystemConstant.ProduceOperation, "All_" + operationItem);

                string v1 = plcDao.GetStringFieldValue(types, SystemConstant.ProduceOperation, "All_" + operationItem + "Ng");

                // 获取工序产量数据
                realCount = decimal.Parse(v.Equals("")
                    ? "0"
                    : v)
                    +
                    realCount;

                realCountNg = decimal.Parse(v1.Equals("")
                    ? "0"
                    : v1)
                    +
                    realCountNg;
            }

            // 包装推送数据
            BossProcess bossProcess = new BossProcess()
            {
                OrderId = orderModel.orderPlan.OrderId,
                ProcessId = operation,
                ProduceAll = realCount,
                ProduceNg = realCountNg
            };

            // 推送
            BossMessager bossMessager = await PutMes.LineMesToMes(bossProcess, SystemConstant.ProduceOperationUrl, $"工序报工，工单号为：{orderModel.orderPlan.OrderId}，工序号为：{operation}，" +
               $"该工序总产量为：{bossProcess.ProduceAll}，该工序Ng产量为：{bossProcess.ProduceNg}，任务推送");

            return bossMessager;
        }

        /// <summary>
        /// 工件下线推送总产量数据
        /// </summary>
        /// <param name="types"></param>
        /// <param name="orderModel"></param>
        private async void LineProcessPut(Dictionary<object, Type> types, PlcOrderConfigModel orderModel, List<string> operationList)
        {
            // 初始化产量字段
            decimal realCount = 0;
            decimal realCountNg = 0;

            // 遍历获取产量
            foreach (var operationItem in operationList)
            {
                // 获取产量字段
                string v = plcDao.GetStringFieldValue(types, SystemConstant.ProduceOperation, "All_" + operationItem);

                string v1 = plcDao.GetStringFieldValue(types, SystemConstant.ProduceOperation, "All_" + operationItem + "Ng");

                // 获取工序产量数据
                realCount = decimal.Parse(v.Equals("")
                    ? "0"
                    : v)
                    +
                    realCount;

                realCountNg = decimal.Parse(v1.Equals("")
                    ? "0"
                    : v1)
                    +
                    realCountNg;
            }

            // 构建数据推送
            BossMessager bossMessager = await PutMes.LineMesToMes(new BossProducePut()
            {
                OrderId = orderModel.orderPlan.OrderId,
                Produce = realCount,
                ProduceNg = realCountNg
            }, SystemConstant.BossProducePutUrl, $"工件下线任务开始推送，工单号为：{orderModel.orderPlan.OrderId}，当前产量为{realCount}，当前Ng产量为{realCountNg}，任务推送");
        }
    }
}
